import tp from 'tp-js-sdk';
import { isMobile } from '@/utils/common';
import { ElMessage } from 'element-plus';
import { useMainStore } from '@/store/index';
import { network } from './network';
import { ethers, utils } from 'ethers';

import usdtContractAbi from '@/a-abi/usdtContractAbi.json';
import axieContractAbi from '@/a-abi/axieContractAbi.json';

export const util = utils;

const rpcProvider = new ethers.providers.JsonRpcProvider(network().rpcUrls[0]);

const web3Provider = (window as any).ethereum || (window as any).okxwallet;

/**choose wallet */
export const chooseWallet = (walletType: string) => {
  const mainStore = useMainStore();
  mainStore.setShowWalletDialog(false);
  if (walletType == 'okxwallet') {
    if (isMobile()) {
      const ua = navigator.userAgent;
      const isOKApp = /OKApp/i.test(ua);
      if (isOKApp) {
        okxConnect(walletType);
      } else {
        ElMessage({ type: 'warning', message: 'Please open your DApp in OKX' });
        setTimeout(() => {
          window.location.href = `okx://wallet/dapp/details?dappUrl=${window.location.origin}`;
        }, 1000);
      }
    } else {
      if (typeof (window as any).okxwallet !== 'undefined') {
        okxConnect(walletType);
      } else {
        ElMessage({ type: 'warning', message: 'Please Install OKX Wallet' });
      }
    }
  } else if (walletType == 'metamask') {
    if (typeof (window as any).ethereum !== 'undefined') {
      okxConnect(walletType);
    } else {
      ElMessage({ type: 'warning', message: 'Please Install MetaMask Wallet' });
    }
  } else if (walletType == 'tp') {
    if (isMobile()) {
      const ua = navigator.userAgent;
      const inApp = /TokenPocket/i.test(ua);
      if (inApp) {
        tpConnect(walletType);
      } else {
        ElMessage({ type: 'warning', message: 'Please open your DApp in TokenPocket' });
        setTimeout(() => {
          window.location.href = `tpdapp://open?params={"url": "${window.location.origin}", "chain": "btc", "source":""}`;
        }, 1000);
      }
    }
  }
};

/**Get Current Wallet */
export const getCurrentWallet = async () => {
  const walletType = localStorage.getItem('walletType');
  if (!walletType) return ElMessage('Please connect wallet');
  if (walletType == 'okxwallet' || walletType == 'metamask') {
    okxConnect(walletType);
  } else if (walletType == 'tp') {
    try {
      const result = await tp.getCurrentWallet();
      if (result.result) {
        if (result.data.blockchain == 'bsc') {
          const mainStore = useMainStore();
          mainStore.setWalletAccount(result.data.address);
          mainStore.setWalletNetwork(true);
          ElMessage({ type: 'success', message: 'Connected' });
        } else {
          tpConnect(walletType);
        }
      }
    } catch (error) {
      console.error('getCurrentWallet failed', error);
    }
  }
};

/**OKX MetaMask */
const okxConnect = async (walletType: string) => {
  localStorage.setItem('walletType', walletType);
  const web3Provider = walletType == 'okxwallet' ? (window as any).okxwallet : (window as any).ethereum;
  const mainStore = useMainStore();
  // EVM
  try {
    const accounts = await web3Provider.request({ method: 'eth_requestAccounts' });
    mainStore.setWalletAccount(accounts[0]);
    ElMessage({ type: 'success', message: 'Connected' });

    const chainId = await web3Provider.request({ method: 'eth_chainId' });

    // mainStore.setWalletNetwork(chainId == network().chainId);
    if (chainId !== network().chainId) {
      await web3Provider.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: network().chainId }] });
    }

    // 移除之前的监听器
    web3Provider.removeAllListeners('accountsChanged');
    web3Provider.removeAllListeners('chainChanged');

    web3Provider.on('accountsChanged', (accounts: any) => {
      if (mainStore.walletAccount == accounts[0]) return;
      mainStore.setWalletAccount(accounts[0]);
      ElMessage({ type: 'success', message: 'Connected' });
    });

    web3Provider.on('chainChanged', async (chainId: any) => {
      mainStore.setWalletNetwork(chainId == network().chainId);
    });
  } catch (error) {
    console.error('connect failed', error);
  }
};

/**TokenPocket */
const tpConnect = async (walletType: string) => {
  localStorage.setItem('walletType', walletType);
  const mainStore = useMainStore();
  try {
    tp.isConnected();
    const result = await tp.getWallet({ walletTypes: ['bsc'], switch: true });
    if (result.result) {
      mainStore.setWalletAccount(result.data.address);
      mainStore.setWalletNetwork(true);
      ElMessage({ type: 'success', message: 'Connected' });
    }
  } catch (error) {
    console.error('connect failed', error);
  }
};

export function getProvider() {
  return new ethers.providers.Web3Provider(web3Provider);
}

export function getSigner() {
  return new ethers.providers.Web3Provider(web3Provider).getSigner();
}

export const usdtContract = (contractUsdt: string) => {
  return new ethers.Contract(contractUsdt, usdtContractAbi, getSigner());
};

export const axieContract = (axieContractAddress: string) => {
  return new ethers.Contract(axieContractAddress, axieContractAbi, getSigner());
};

export async function getBnbBalance(walletAccount: string) {
  const res = await rpcProvider.getBalance(walletAccount);
  const balance = Number(util.formatEther(res));
  // console.log('BNB: ', balance);
  return balance;
}

export async function getUsdtBalance(instance: any, walletAccount: string) {
  const res = await instance.balanceOf(walletAccount);
  const balance = Number(util.formatEther(res));
  // console.log('USDT: ', balance);
  return balance;
}

export async function getAxieBalance(instance: any, walletAccount: string) {
  const res = await instance.balanceOf(walletAccount);
  const balance = Number(util.formatEther(res));
  // console.log('AXIE: ', balance);
  return balance;
}
